package net.sf.nlp.ltag.extract;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import net.sf.nlp.ltag.data.ExtractedTree;
import net.sf.nlp.ltag.data.LTAGTree.TreeType;

import org.apache.log4j.Logger;

public class ExtractBatch 
{
	private static final String CTB_FILE_EXTENSION = ".ctb";
	
	protected static Logger logger =  Logger.getLogger(ExtractBatch.class);
	protected static Logger debugLogger =  Logger.getLogger("net.sf.nlp.ltag.extract.debug-info");
	
	private ExtractLTAG extractLTAG = new ExtractLTAG();
	private List<File> ctbFiles = new ArrayList<File>();
	
	public void extract(String fileName, boolean isPersistence) throws Exception
	{
		ctbFiles.clear();
		
		File file = new File(fileName);
		
		if (!file.exists())
			logger.warn("The " + fileName + " is not existed!");
		
		loadDirectoryRecursively(file);
		
		List<ExtractedTree> etrees = new ArrayList<ExtractedTree>();
		
		for (File ctbFile : ctbFiles)
			etrees.addAll(extract(ctbFile));
		
		if (isPersistence)
			new ExtractPersistence().saveTrees(etrees);
		
		//convert2SuperLTAG(etrees);
	}
	/*
	private void convert2SuperLTAG(List<ExtractedTree> etrees) throws Exception
	{
		Map<String, SuperLTAG> ltagMap = new HashMap<String, SuperLTAG>();
		
		for (ExtractedTree etree : etrees)
		{
			try
			{
				String superLTAGString = etree.toSuperLTAG();
				
				SuperLTAG superLTAG = ltagMap.get(superLTAGString);
				
				if (superLTAG == null)
				{
					superLTAG = new SuperLTAG();
					
					LTAGNode root = LTAG.buildLTAGNodeFromText(superLTAGString);
					if (root == null)
						continue;
					
					LTAGTree tree = new LTAGTree();
					tree.setRoot(root);
					tree.validate();
					
					superLTAG.setSuperTree(tree);
					ltagMap.put(superLTAGString, superLTAG);
				}
				
				superLTAG.getEtrees().add(etree);
			}
			catch(Exception ex)
			{
				logger.error("The tree [" + etree + "] is wrong!", ex);
			}
		}
		
		printLTAG(ltagMap, StringType.LTAG);
	}
	
	private void printLTAG(Map<String, SuperLTAG> ltagMap, StringType stringType)
	{
		Iterator<String> keys = ltagMap.keySet().iterator();
		
		logger.info("------------------EXTRACT LTAG [" + ltagMap.keySet().size() + "]---------------");
		while (keys.hasNext())
		{
			SuperLTAG superLTAG = ltagMap.get(keys.next());
			
			logger.info(superLTAG.getSuperTree().toSuperLTAG() + "[" + superLTAG.getEtrees().size() + "]");
			if (stringType != StringType.SuperLTAG)
			{
				for (ExtractedTree etree : superLTAG.getEtrees())
					logger.info(" >> " + etree.toLTAG());
			}
		}
		logger.info("---------------------------------------------");
	}
*/
	public List<ExtractedTree> extract (File ctbFile)
	{
		logger.info("processing " + ctbFile.getName());
		
		List<ExtractedTree> etrees = new ArrayList<ExtractedTree>();
		
		try
		{
			BufferedReader reader = new BufferedReader(new FileReader(ctbFile));
			
			StringBuffer bracketedTree = new StringBuffer();
			String line = null;
			
			while ((line = reader.readLine()) != null)
			{
				try
				{
					if (line.trim().length() == 0)
					{
						if (bracketedTree.length() > 0)
						{
							String tree = bracketedTree.toString();
							bracketedTree.delete(0, bracketedTree.length());
							
							ExtractResult extractResult = extractLTAG.extract(tree);
							
							if (extractResult == null)
								continue;
							
							extractResult.setOriginalTree(tree);
							saveExtractedDebug(ctbFile, extractResult);
							
							if (extractResult.getEtrees() != null)
								etrees.addAll(extractResult.getEtrees());
						}
					}
					else
					{
						bracketedTree.append(line).append("\r\n");
					}
				}
				catch(Exception ex)
				{
					logger.error(bracketedTree.toString());
					logger.error(ex, ex);
				}
			}
			
			reader.close();
		}
		catch(Exception ex)
		{
			logger.error(ex, ex);
		}
		
		return etrees;
	}

	
	private void loadDirectoryRecursively(File file) {
		if (!file.isDirectory()) {
			ctbFiles.add(file);
		} else {
			File[] files = file.listFiles(new FileFilter() 
			{
				public boolean accept(File file) {
					if (file.isDirectory())
						return true;

					if (file.getName().toLowerCase().endsWith(CTB_FILE_EXTENSION))
						return true;

					return false;
				}
			});

			for (File xmlFile : files)
				loadDirectoryRecursively(xmlFile);
		}
	}
	
	private void saveExtractedDebug(File ctbFile, ExtractResult extractResult) throws IOException
	{
		if (!debugLogger.isDebugEnabled())
			return;
		
		int superLTAGPos =100;
		
		debugLogger.debug("[" + ctbFile.getName() + "]:");
		debugLogger.debug("Orignial Tree:\r\n" + extractResult.getOriginalTree());
		debugLogger.debug("Full Bracked Tree:\r\n" + extractResult.getBrackedTree().toString());
		debugLogger.debug("-----------------------------------");
		
		List<ExtractedTree> etrees = extractResult.getEtrees();
		int iTreeCount = 0, aTreeCount = 0;
		
		for (ExtractedTree t : etrees)
		{
			if (t.getType() == TreeType.I)
				iTreeCount++;
			else if (t.getType() == TreeType.A)
				aTreeCount++;
			
			StringBuffer sb = new StringBuffer();
			sb.append(t.toString());
			int i = superLTAGPos - sb.length();
			for (; i < superLTAGPos; i++)
				sb.append(" ");
			sb.append(t.toSuperLTAG());
			
			debugLogger.debug(sb.toString());
		}
		debugLogger.debug("Summary: Init Tree=" + iTreeCount + "; Auxiliary Tree=" + aTreeCount);
		
		debugLogger.debug("-----------------------------------");
	}
	
	public static void main(String[] args) throws Exception
	{
		try
		{
			String path = "C:/NLP/语料/ctb8.0/data/standard/";
			//String path = "C:/NLP/Projects/nlp-toolkit/resource/parser/";
			ExtractBatch extract = new ExtractBatch();
			
			extract.extract(path, true);
		}
		catch(Exception ex)
		{
			logger.error(ex, ex);
		}
	}
}
